#include <sys/param.h>
#include <sys/systm.h>
#include <sys/ioctl.h>
#include <sys/cdefs.h>
#include <sys/conf.h>
#include <sys/mount.h>
#include <sys/exec.h>
#include <sys/lkm.h>
#include <sys/proc.h>
#include <sys/syscallargs.h>


/* our system call prototype */
int	newcall __P((struct proc *p, void *uap, int *retval));

/*
 * All system calls are passed three arguments: a pointer to the 
 * struct proc that is calling it, a void pointer to its arguments
 * and an integer pointer to it's return value. Here we define a 
 * structure for the arguments. If you only have one argument, 
 * create your structure with just one entry.
 */

struct newcall_args{
	syscallarg(int) value;
	syscallarg(char *) msg;
};

/* 
 * This structure defines our system call. The first argument is the 
 * number of arguments, the second argument is the size of the 
 * arguments and the third argument the function that contains the 
 * actual code for the system call.
 */

static struct sysent newcallent = {
	2, sizeof(struct newcall_args), newcall 
};

/* 
 * Initialise an internal structure for our syscall. 
 * Argument 1 is the name of the syscall used for (among other things)
 * lookups in the ioctl() call. Argument 2 is the slot where the system 
 * call function pointer should be placed. You can either pass the 
 * number you want, or -1 which indicates the next available slot 
 * should be used. Argument 3 is a pointer to a struct sysent for the 
 * call.
 */	

MOD_SYSCALL("ourcall", -1, &newcallent);

/*
 * This function will be used when our module is being "wired in".
 * It is passed a pointer to a struct lkm_table and the command or 
 * action that is being performed. Checking the value of the command 
 * as we do below allows a generic "handler" if desired. When adding
 * a system call via a module, there is no special handling performed
 * for the stat action.
 */

static int
ourcall_handler(lkmtp, cmd)
	struct lkm_table *lkmtp;
	int	cmd;
{
	if (cmd == LKM_E_LOAD) 
		printf("hi!\n");
	else if (cmd == LKM_E_UNLOAD)
		printf("bye!\n");

	return(0);
}

/* 
 * This is the external entry point for our module.  As above we are
 * passed a command describing the action being performed and allowing generic
 * handlers. We are also passed a version number to allow one module to
 * contain the source for future versions of the lkm interface. 
 *
 * The macro DISPATCH is additionally passed three arguments specifying
 * the code that will be called for the actions load, unload and stat.
 * For load and unload we share the function ourcall_handler(). For stat 
 * (which is unused when adding system calls) we use lkm_nofunc() which
 * is simply a stub that returns 0.
 */

int
ourcall(lkmtp, cmd, ver)
	struct lkm_table *lkmtp;
	int	cmd;
	int	ver;
{
	DISPATCH(lkmtp, cmd, ver, ourcall_handler, ourcall_handler, lkm_nofunc);
}

/* 
 * Finally we have the code for our actual new system call. The arguments
 * passed to it are at the void pointer.
 */

int
newcall(p, v, retval)
	struct proc *p;
	void *v;
	int *retval;
{
	struct newcall_args *uap = v;

	printf("%d %s\n", SCARG(uap, value), SCARG(uap, msg));
	return(0);
}
